# -*- coding: utf-8 -*-

__author__="Hugo Poloni"
__date__ ="$20/11/2009$"

import os
import re
import uuid
import tempfile

from PyQt4.QtCore import QObject, QByteArray, QUrl, QFile, SIGNAL
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkCookieJar, QNetworkCookie

class FuncType:
    LOGIN = 'FUNC_LOGIN'
    LOGOUT = 'FUNC_LOGOUT'
    SEARCH = 'FUNC_SEARCH'
    DOWNLOAD = 'FUNC_DOWNLOAD'

class LoginOpt:
    DONT_STAY_LOGGED = '0'
    STAY_LOGGED = '1'

class SearchType:
    RELEASE = '1'
    MOVIE = '2'
    USER = '3' # Not supported

class SearchLang:
    PT_BR = '1'
    PT_PT = '10'
    EN = '2'
    ES = '3'
    OTHER = '100'
    ALL = '99'

class QNetworkCookieJarPerssistant(QNetworkCookieJar):

    def __init__ (self, cookie_dir=None ,parent=None):
        QNetworkCookieJar.__init__(self, parent)

        COOKIE_FILE_NAME = 'ltvCookies.txt'

        if not cookie_dir:
            cookie_dir = tempfile.gettempdir()

        path = os.path.join(cookie_dir, COOKIE_FILE_NAME)
        self.cookie_path = os.path.abspath(path)

        self._readCookieFile()

    def _readCookieFile(self):

        out_f = QFile(self.cookie_path)
        if out_f.open(QFile.ReadOnly):
            data = out_f.readAll()
            cookies = QNetworkCookie.parseCookies(data)
            self.setAllCookies(cookies)

    def setCookiesFromUrl (self, cookieList, url):

        ret_value = QNetworkCookieJar.setCookiesFromUrl(self, cookieList, url)

        out_f = QFile(self.cookie_path)
        if out_f.open(QFile.WriteOnly):
            cookies = self.allCookies()

            for c in cookies:
                out_f.write(c.toRawForm())
                out_f.write('\n')
            out_f.close()

        return ret_value

class LibLTV(QObject):

    def __init__(self, username, password, download_dir=None):
        QObject.__init__(self)

        if not download_dir:
            download_dir = tempfile.gettempdir()

        self.DOWNLOAD_PATH = os.path.abspath(download_dir)

        self.username = username
        self.password = password

        self.entry_re = re.compile('javascript:abredown\(\'(?P<downcode>\w+)\'.+?Downloads: </b> (?P<downloads>\d+).+?flag_(?P<lang>[a-z][a-z]).+?brls\">(?P<release>.+?)</span>',re.DOTALL)

        self.number_conn = 0
        self.max_conn = 5
        self.conected = True

        self.queue = []
        self.pending = {}
        self.hash = {}

        self.conn = QNetworkAccessManager()
        cookieJar = QNetworkCookieJarPerssistant(self.DOWNLOAD_PATH)
        self.conn.setCookieJar(cookieJar)

        self.connect(self.conn, SIGNAL("finished(QNetworkReply*)"), self._proccess_reply)

    def login(self, login, password, login_opt=LoginOpt.DONT_STAY_LOGGED):
        '''LoginForm:
            txtLogin -> max_length(15)
            txtSenha -> max_length(15)
            chkLogin -> 0|1 (keep logged?)
        '''
        LOGIN_URL = QUrl('http://legendas.tv/login_verificar.php')
        params = QByteArray('txtLogin=' + login + '&txtSenha=' + password + '&chkLogin=' + login_opt)

        req = QNetworkRequest(LOGIN_URL)
        id = uuid.uuid1()

        self.queue.insert(0, (id, FuncType.LOGIN, [req, params]))
        self._send_request(override_check=True)

        return id

    def logout(self):

        LOGOFF_URL =  QUrl('http://legendas.tv/logoff.php')

        req = QNetworkRequest(LOGOFF_URL)

        id = uuid.uuid1()

        self.queue.insert(0, (id, FuncType.LOGIN, [req, '']))
        self._send_request()

        return id

    def search(self, p_query, p_search_type=SearchType.RELEASE, p_lang=SearchLang.PT_BR):
        '''SearchForm:
            txtLegenda -> 15
            selTipo -> 1 Release / 2 Filme / 3 Usuario
            int_idioma -> 99 Todos / 1 PT-BR
        '''
        SEARCH_URL = QUrl('http://legendas.tv/index.php?opcao=buscarlegenda')
        rls_name = p_query.replace(' ', '+')

        params = QByteArray('txtLegenda=' + rls_name + '&selTipo=' + p_search_type + '&int_idioma=' + p_lang)


        req = QNetworkRequest(SEARCH_URL)
        id = uuid.uuid1()

        self.queue.append((id, FuncType.SEARCH, [req, params]))
        self._send_request()

        return id

    def download_sub(self, code):

        GET_FILE_URL = QUrl('http://legendas.tv/info.php?d=' + code + '&c=1')
        req = QNetworkRequest(GET_FILE_URL)
        req.setRawHeader('User-agent', 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.0 (KHTML, like Gecko) Chrome/3.0.195.33 Safari/532.0')

        id = uuid.uuid1()
        self.queue.append((id, FuncType.DOWNLOAD, [req]))
        self._send_request()

        return id

    def _download_sub_file(self, id, url):

        url = QUrl(str(url))
        req = QNetworkRequest(url)

        self.queue.append((id, FuncType.DOWNLOAD, [req]))
        self._send_request()

    def _send_request(self, override_check=False):

        if not override_check:
            if self.number_conn > self.max_conn or not self.conected:
                return

        if len(self.queue) == 0:
            return

        self.number_conn += 1

        temp = self.queue.pop(0)
        id = temp[0]
        func_type = temp[1]
        params = temp[2]

        if func_type in [FuncType.LOGIN, FuncType.LOGOUT, FuncType.SEARCH]:
            reply = self.conn.post(*params)
        else:
            reply = self.conn.get(*params)

        self.hash[reply] = id
        self.pending[id] = (func_type, params)

    def _resend_request(self, reply):

        id = self.hash.pop(reply)
        func_type, params = self.pending.pop(id)
        self.queue.insert(0, (id, func_type, params))
        self._send_request()

    def _check_reply(self, reply, data):

        statusCode = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute).toInt()[0]
        contentType = reply.header(QNetworkRequest.ContentTypeHeader).toString()

        if statusCode not in [200, 302]:
            self._resend_request(reply)
            #signal error??
            return False

        if contentType == 'application/x-rar-compressed':
            return True

        html = str(data)

        if html.find('precisa estar logado para acessar essa') > -1:
            print u'Você precisa estar logado para acessar essa área!'
            self.conected = False
            self.login(self.username, self.password)
            self._resend_request(reply)
            return False
        elif html.find('F5 dentro de alguns instantes') > -1:
            print u'O Legendas.tv está sobrecarregado...'
            self._resend_request(reply)
            #server busy signal???
            #block send for some time to avoid server overload?
            return False
        else:
            return True

    def _proccess_reply(self, reply):

        self.number_conn -= 1
        data = reply.readAll()

        if not self._check_reply(reply, data):
            return

        id = self.hash.pop(reply)
        req_type = self.pending.pop(id)[0]

        if req_type == FuncType.LOGIN:
            html = str(data)
            if html.find('Bem vindo(a)') > -1:
                print 'Bem Vindo!!!! Você está logado'
                #signal loginSuccessful???
                self.conected = True
            elif html.find('Dados incorretos!') > -1:
                print 'Dados incorretos!'
                self.emit(SIGNAL('badLoginData()'))

        elif req_type == FuncType.LOGOUT:
            print 'Logged out'

        elif req_type == FuncType.SEARCH:
            html = str(data)
            items = self._parse_search(html)
            print 'searchFinished(id, items)'
            self.emit(SIGNAL("searchFinished(id, items)"), id, items)

        elif req_type == FuncType.DOWNLOAD:
            statusCode = reply.attribute(QNetworkRequest.HttpStatusCodeAttribute).toInt()[0]
            if statusCode == 302:
                    url = 'http://legendas.tv/' + reply.rawHeader('Location')
                    print 'Download Redirect', url
                    self._download_sub_file(id, url)
            else:
                filename = reply.url().toString().split('/')[-1]
                filepath = self._parse_download(str(filename), data)
                print 'downloadFinished()'
                if filepath:
                    self.emit(SIGNAL("downloadFinished(id, filepath)"), id, filepath)
                else:
                    #error
                    pass

        self._send_request()

    def _parse_search(self, html):

        entries = self.entry_re.findall(html)
        return entries

    def _parse_download(self, filename, data):

        file_path = os.path.join(self.DOWNLOAD_PATH, filename)
        abs_path = os.path.abspath(file_path)

        out_f = QFile(abs_path)

        if out_f.open(QFile.WriteOnly):
            out_f.write(data)
            out_f.close()
            return abs_path
        else:
            return
